package com.orientation.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orientation.commom.exception.CustomException;
import com.orientation.dto.MajorDto;
import com.orientation.entity.Class;
import com.orientation.entity.*;
import com.orientation.mapper.*;
import com.orientation.service.*;
import com.orientation.utils.PageUtils;
import com.orientation.vo.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 学院 服务实现类
 * </p>
 *
 * @author xuandian
 * @since 2022-3-9
 */
@Service
public class CollegeServiceImpl extends ServiceImpl<CollegeMapper, College> implements CollegeService {
    @Resource
    private MajorService majorService;

    @Resource
    private StudentService studentService;
    @Resource
    private CollegeMapper collegeMapper;
    @Resource
    private MajorMapper majorMapper;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private CollegeService collegeService;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private ClassService classService;
    @Resource
    private ReserveMapper reserveMapper;
    @Resource
    private ReserveService reserveService;


    /**
     * 学院男女信息统计
     *
     * @return
     */
    @Override
    public List<CollegeInfoVo> findCollegeInfo() {
        List<CollegeInfoVo> collegeInfoVoList = new ArrayList<>();
        for (College college : list()) {
            CollegeInfoVo collegeInfoVo = new CollegeInfoVo();
            collegeInfoVo.setName(college.getCollegeName());
            //根据学院id去数据库擦查询对应的专业信息
            List<Major> majorList = majorService.findByCollegeId(college.getSid());
            //取专业名
            List<String> majorNameList = majorList.stream().map(Major::getMajorName).collect(toList());
            collegeInfoVo.setMajorList(majorNameList);
            long boyCount = studentService.countByCollegeIdAndGender(college.getSid(), "男");
            long girlCount = studentService.countByCollegeIdAndGender(college.getSid(), "女");
            List<PieDataVo> pieDataVoList = new ArrayList<>();
            PieDataVo boyPie = new PieDataVo();
            boyPie.setName("男");
            boyPie.setValue(boyCount);
            pieDataVoList.add(boyPie);
            PieDataVo girlPie = new PieDataVo();
            girlPie.setName("女");
            girlPie.setValue(girlCount);
            pieDataVoList.add(girlPie);
            collegeInfoVo.setPieData(pieDataVoList);
            collegeInfoVo.setAllCount(boyCount + girlCount);
            collegeInfoVoList.add(collegeInfoVo);
        }
        return collegeInfoVoList;
    }

    //todo 残次代码  不符合预期结果  匹配问题
    @Override
    public List<CollegeInfoVo> queryCollegeInfo(String collegeName, String majorName, String collegeId) {
        List<CollegeInfoVo> collegeInfoVoList = new ArrayList<>();
        LambdaQueryWrapper<College> query = new LambdaQueryWrapper<>();
        // query.eq(College::getDeleted, 0);
        if (!StringUtils.isEmpty(collegeName)) {
            query.like(College::getCollegeName, collegeName);
        }
        List<College> collegeList = collegeMapper.selectList(query);
        List<College> collect = new ArrayList<>();
        if (!CollectionUtils.isEmpty(collegeList)) {
            //去重后的记录
            collect = collegeList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getCollegeName()))), ArrayList::new));

        }

        LambdaQueryWrapper<Major> queryWrapper = new LambdaQueryWrapper<>();
        //  queryWrapper.eq(Major::getDeleted, 0);
        if (!StringUtils.isEmpty(majorName) && !StringUtils.isEmpty(collegeId)) {
            queryWrapper.eq(Major::getMajorName, majorName).eq(Major::getCollegeId, collegeId);
        }
        List<Major> majorList = new ArrayList<>();
        List<Major> majors = majorMapper.selectList(queryWrapper);
        List<String> strings = majors.stream().map(Major::getSid).distinct().collect(toList());
        if (!CollectionUtils.isEmpty(majors)) {
            majorList = majors.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getMajorName()))), ArrayList::new));
        }
        List<PieDataVo> pieDataVoList = new ArrayList<>();
        //对应专业下的所有学生
        List<Student> students = studentMapper.selectList(new LambdaQueryWrapper<Student>()
                //  .eq(Student::getDeleted, 0).
                .in(Student::getMajorId, strings));

        if (!CollectionUtils.isEmpty(strings)) {

            //去重
            List<Student> studentList = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getIdCardNo()))), ArrayList::new));
            Map<String, List<Student>> stringListMap = studentList.stream().collect(Collectors.groupingBy(Student::getMajorId));
            //筛选男女信息
            List<Student> girlList = studentList.stream().filter((Student student) -> "女".equals(student.getGender())).collect(toList());
            List<Student> boyList = studentList.stream().filter((Student student) -> "男".equals(student.getGender())).collect(toList());
            //long boyCount = boyList.size();
//            AtomicLong boyCount= new AtomicLong();
            long girlCount = girlList.size();
            //   List<Major> finalMajorList = majorList;
            int i = 0;
/*            stringListMap.forEach((majorId, value) -> {
                for (Major major : finalMajorList) {
                    value.forEach(student -> {
                        if (student.getMajorId().equals(major.getSid()) && "男".equals(student.getGender())) {

                          //   boyCount.set(value.size());
                        }
                    });
                }
            });*/

            //TODO 信息匹配错误
            for (College college : collect) {
                for (Major major : majorList) {
                    if (college.getSid().equals(major.getCollegeId())) {
                        CollegeInfoVo collegeInfoVo = new CollegeInfoVo();
                        PieDataVo boyPie = new PieDataVo();
                        collegeInfoVo.setName(college.getCollegeName());
                        boyPie.setName("男");
                        boyPie.setMajorName(major.getMajorName());
                        //    boyPie.setValue(boyCount);
                        pieDataVoList.add(boyPie);
                        PieDataVo girlPie = new PieDataVo();
                        girlPie.setName("女");
                        girlPie.setMajorName(major.getMajorName());
                        girlPie.setValue(girlCount);
                        pieDataVoList.add(girlPie);
                        collegeInfoVo.setPieData(pieDataVoList);
                        //    collegeInfoVo.setAllCount(boyCount + girlCount);
                        collegeInfoVoList.add(collegeInfoVo);
                        //  break;
                    }

                }
            }
        }

        return collegeInfoVoList;
    }


    @Override
    public List<CollegeMajorVo> MajorVos() {
        List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>()
                //.eq(Major::getDeleted, 0)
                .eq(Major::getState, 1));
        List<CollegeMajorVo> collegeMajorVos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(majors)) {
            //根据学院id重后查询
            List<Major> distinct = majors.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getMajorName()))), ArrayList::new));
            //根据专业id分组
            //Map<String, List<Major>> integerListMap = distinct.stream().collect(Collectors.groupingBy(Major::getCollegeId));
            //获取学院id
            //List<String> strings = distinct.stream().map(Major::getCollegeId).distinct().collect(Collectors.toList());
            List<String> strings = distinct.stream().map(Major::getCollegeId).distinct().collect(toList());
            List<College> colleges = collegeMapper.selectList(new LambdaQueryWrapper<College>()
                    //    .eq(College::getDeleted, 0).
                    .in(College::getSid, strings));

            List<MajorDto> majorDtos = new ArrayList<>();
            for (Major major : distinct) {
                MajorDto majorDto = new MajorDto();
                majorDto.setSid(major.getSid());
                majorDto.setMajorName(major.getMajorName());
                majorDto.setCollegeId(major.getCollegeId());
                majorDtos.add(majorDto);
            }
//            根据专业id分组
            Map<String, List<MajorDto>> integerListMap = majorDtos.stream().collect(Collectors.groupingBy(MajorDto::getCollegeId));
/*// 根据学院id重后查询
//             List<College> collegeDistinct = majors.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.get()))), ArrayList::new));
//            根据专业id分组
            Map<String, List<String>> stringStringMap = new HashMap<>();
            integerListMap.forEach((CollegeId, Value) -> {
                for (College college : colleges) {
                    {
                        List<String> majorNameList = new ArrayList<>();
                        if (CollegeId.equals(college.getSid())) {
                            Value.forEach(major -> {
                                majorNameList.add(major.getMajorName());
                                stringStringMap.put(CollegeId, majorNameList);
                            });
                        }
                    }
                }
            });*/

            if (!CollectionUtils.isEmpty(colleges)) {
                for (College college : colleges) {
                    for (MajorDto majorDto : majorDtos) {
                        if (college.getSid().equals(majorDto.getCollegeId())) {
                            CollegeMajorVo collegeMajorVo = new CollegeMajorVo();
                            collegeMajorVo.setCollegeId(college.getSid());
                            collegeMajorVo.setMajorDtoList(integerListMap.get(majorDto.getCollegeId()));
                            collegeMajorVo.setCollegeName(college.getCollegeName());
                            collegeMajorVos.add(collegeMajorVo);
                            break;
                        }
                    }
                }
            }
        }
        return collegeMajorVos;
    }

    @Override
    public List<College> getAllCollege() {
        List<College> collegeList = collegeMapper.selectList(new LambdaQueryWrapper<College>()
                // .eq(College::getDeleted, 0)
        );
        //去重后
        List<College> distinct = collegeList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getCollegeName()))), ArrayList::new));
        if (!CollectionUtils.isEmpty(distinct)) {
            comparatorForChina(distinct);
        }
        return distinct;
    }

    @Override
    public IPage<College> getCollege(Integer pageNum, Integer pageSize, String collegeName) {
        Page<College> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<College> query = new LambdaQueryWrapper<>();
        //   query.eq(College::getDeleted, 0);
        if (!StringUtils.isEmpty(collegeName)) {
            query.like(College::getCollegeName, collegeName);
        }
        page = collegeMapper.selectPage(page, query);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            throw new CustomException("18", "当前暂无数据");
        } //中文排序
        comparatorForChina(page.getRecords());
        List<College> collegeList = page.getRecords();
        //去重
        List<College> collect = collegeList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getCollegeName()))), ArrayList::new));
        //去重后的记录
        page.setRecords(collect);
        //去重后的总记录数量
        page.setTotal(collect.size());
        return page;
    }


    @Override
    @Transactional
    public void insertCollege(College college) {
        if (college != null && !StringUtils.isEmpty(college.getCollegeName())) {
            List<College> collegeList = collegeMapper.selectList(new LambdaQueryWrapper<College>()
                    // .eq(College::getDeleted, 0)
                    .eq(College::getCollegeName, college.getCollegeName())
            );
            if (!CollectionUtils.isEmpty(collegeList)) {
                throw new CustomException("18", "当前学院已经存在");
            } else {
                if (!StringUtils.isEmpty(college.getCollegeCode())&&college.getCollegeCode().length()!=2) {
                    throw new CustomException("18", "输入code信息错误");
                }
                this.save(college);
            }
        }
    }

    @Override
    public List<CollegeTreeVo> findTree(String adviserId) {
        List<CollegeTreeVo> collegeTreeVoList = new ArrayList<>();
        List<Major> majorsList = majorService.list(Wrappers.<Major>lambdaQuery().eq(Major::getAdviserId, adviserId));
        if (!CollectionUtils.isEmpty(majorsList)) {
            //去重
            ArrayList<Major> arrayList = majorsList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getAdviserId()))), ArrayList::new));
            List<String> majorIds = arrayList.stream().map(Major::getCollegeId).distinct().collect(toList());

            List<College> collegeList = collegeService.list(Wrappers.<College>lambdaQuery().in(College::getSid, majorIds));
            if (!CollectionUtils.isEmpty(collegeList)) {
                for (College college : collegeList) {
                    CollegeTreeVo collegeTreeVo = new CollegeTreeVo();
                    collegeTreeVo.setId(college.getSid());
                    collegeTreeVo.setLabel(college.getCollegeName());
                    List<CollegeTreeVo> majorList = new ArrayList<>();

                    List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>()
                            .eq(Major::getCollegeId, college.getSid())
                    );
                    //majorService.list(Wrappers.<Major>lambdaQuery().eq(Major::getCollegeId, college.getSid()))
                    for (Major major : majors) {
                        CollegeTreeVo majorTreeVo = new CollegeTreeVo();
                        majorTreeVo.setId(major.getSid());
                        majorTreeVo.setLabel(major.getMajorName());
                        majorList.add(majorTreeVo);
                    }
                    collegeTreeVo.setChildren(majorList);
                    collegeTreeVoList.add(collegeTreeVo);
                }
            }
        }
        return collegeTreeVoList;
    }

    @Override
    public List<CollegeTreeVo> ThreeTree(String adviserId) {
        List<CollegeTreeVo> collegeTreeVoList = new ArrayList<>();
        List<String> majorIds = new ArrayList<>();
        if (!StringUtils.isEmpty(adviserId)) {
            List<Major> majorsList = majorService.list(Wrappers.<Major>lambdaQuery().eq(Major::getAdviserId, adviserId));
            if (!CollectionUtils.isEmpty(majorsList)) {
                //去重
                ArrayList<Major> arrayList = majorsList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getAdviserId()))), ArrayList::new));
                majorIds = arrayList.stream().map(Major::getCollegeId).distinct().collect(toList());
            } else {
                throw new CustomException("18", "暂无权限查看");
            }
        }

        List<College> collegeList = collegeService.list(Wrappers.<College>lambdaQuery().in(!CollectionUtils.isEmpty(majorIds), College::getSid, majorIds).ne(College::getCollegeName, "全学院"));
        if (!CollectionUtils.isEmpty(collegeList)) {
            for (College college : collegeList) {
                CollegeTreeVo collegeTreeVo = new CollegeTreeVo();
                collegeTreeVo.setId(college.getSid());
                collegeTreeVo.setLabel(college.getCollegeName());
                List<CollegeTreeVo> majorList = new ArrayList<>();

                List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>()
                        .eq(Major::getCollegeId, college.getSid())
                );
                //majorService.list(Wrappers.<Major>lambdaQuery().eq(Major::getCollegeId, college.getSid()))
                for (Major major : majors) {
                    CollegeTreeVo majorTreeVo = new CollegeTreeVo();
                    majorTreeVo.setId(major.getSid());
                    majorTreeVo.setLabel(major.getMajorName());
                    majorList.add(majorTreeVo);

                    List<Class> classes = classMapper.selectList(new LambdaQueryWrapper<Class>()
                            .eq(Class::getMajorId, major.getSid())
                    );
                    List<CollegeTreeVo> classList = new ArrayList<>();
                    for (Class ignored : classes) {
                        if (ignored.getMajorId().equals(major.getSid())) {
                            CollegeTreeVo classTreeVo = new CollegeTreeVo();
                            classTreeVo.setId(ignored.getSid());
                            classTreeVo.setLabel(ignored.getClassName());
                            classList.add(classTreeVo);
                        }
                        majorTreeVo.setChildren(classList);
                    }
                }
                collegeTreeVo.setChildren(majorList);
                collegeTreeVoList.add(collegeTreeVo);
            }
        }

        return collegeTreeVoList;
    }


    @Override
    public Page<ReserveCollegeVo> queryReserveRate(Integer pageNum, Integer pageSize, String collegeId, String majorId, String classId, String type) {
        List<ReserveCollegeVo> reserveCollegeVos = new ArrayList<>();
        List<Student> students = studentService.list(Wrappers.<Student>lambdaQuery().eq(StringUtils.isNotEmpty(collegeId), Student::getCollegeId, collegeId).
                eq(StringUtils.isNotEmpty(majorId), Student::getMajorId, majorId)
                .eq(StringUtils.isNotEmpty(classId), Student::getClassId, classId));
        if (!CollectionUtils.isEmpty(students)) {
            List<String> studentIds = students.stream().map(Student::getStudentId).distinct().collect(toList());
            List<String> collectIds = students.stream().map(Student::getCollegeId).distinct().collect(toList());
            List<String> majorIds = students.stream().map(Student::getMajorId).distinct().collect(toList());
            List<String> classIds = students.stream().map(Student::getClassId).distinct().collect(toList());
            List<Class> classes = classService.list(Wrappers.<Class>lambdaQuery().in(!CollectionUtils.isEmpty(classIds), Class::getSid, classIds));
            List<Reserve> reservations = reserveService.list(Wrappers.<Reserve>lambdaQuery().in(!CollectionUtils.isEmpty(studentIds), Reserve::getStudentId, studentIds));
            List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>().in(Major::getSid, majorIds));
            //   Map<String, List<Major>> majorsMap = majors.stream().collect(Collectors.groupingBy(Major::getSid));
            List<College> colleges = collegeMapper.selectList(new LambdaQueryWrapper<College>().in(College::getSid, collectIds));
            //   Map<String, List<College>> collegeMap = colleges.stream().collect(Collectors.groupingBy(College::getSid));
            Map<String, List<Student>> studentMap = students.stream().collect(Collectors.groupingBy(Student::getCollegeId));
            if (StringUtils.isEmpty(classId) && StringUtils.isEmpty(majorId) && ("1".equals(type))) {
                //学院维度
                studentMap.forEach((college, Value) -> {
                        //学院总维度
                    //  根据学生id取交集
                    List<Reserve> reserveList = reservations.stream().filter(m -> Value.stream().map(Student::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());
                    ReserveCollegeVo reserveCollegeVo = getReserveRate(reserveList, Value.size());
                    //  总应该报道人数
                    reserveCollegeVo.setStudentTotalNum(Value.size());
                    for (College c : colleges) {
                        if (c.getSid().equals(college)) {
                            reserveCollegeVo.setName(c.getCollegeName());
                        }
                    }
                    reserveCollegeVos.add(reserveCollegeVo);
                });
            } else if (StringUtils.isEmpty(classId) && StringUtils.isEmpty(collegeId) && "2".equals(type)) {
                //专业总维度
                Map<String, List<Student>> studentMajorId = students.stream().collect(Collectors.groupingBy(Student::getMajorId));
                studentMajorId.forEach((studentMajor, studentList) -> {
                    //  根据学生id取交集
                    List<Reserve> reserveList = reservations.stream().filter(m -> studentList.stream().map(Student::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());
                    ReserveCollegeVo reserveCollegeVo = getReserveRate(reserveList, studentList.size());
                    reserveCollegeVo.setStudentTotalNum(studentList.size());
                    for (Major c : majors) {
                        if (c.getSid().equals(studentMajor)) {
                            reserveCollegeVo.setName(c.getMajorName());
                        }
                    }
                    reserveCollegeVos.add(reserveCollegeVo);
                });
            } else if (StringUtils.isEmpty(majorId) && StringUtils.isEmpty(collegeId) && "3".equals(type)) {
                //班级维度
                Map<String, List<Student>> studentClassId = students.stream().collect(Collectors.groupingBy(Student::getClassId));
                studentClassId.forEach((studentClass, classValue) -> {
                    List<Reserve> reserveList = reservations.stream().filter(m -> classValue.stream().map(Student::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());
                    ReserveCollegeVo reserveCollegeVo = getReserveRate(reserveList, classValue.size());
                    reserveCollegeVo.setStudentTotalNum(classValue.size());
                    for (Class clazz : classes) {
                        if (clazz.getSid().equals(studentClass)) {
                            reserveCollegeVo.setName(clazz.getClassName());
                        }
                    }
                    reserveCollegeVos.add(reserveCollegeVo);
                });
            }
        }
        return PageUtils.getPage(reserveCollegeVos, pageNum, pageSize);
    }

    private ReserveCollegeVo getReserveRate(List<Reserve> reserveList, Integer ValueNum) {
        ReserveCollegeVo reserveCollegeVo = new ReserveCollegeVo();
        //目前总报道人数
        long studentAlreadyNum = reserveList.stream().filter(reserve -> reserve.getStatus().equals(3)).count();
        reserveCollegeVo.setStudentAlreadyNum((int) studentAlreadyNum);

        BigDecimal alreadyRate = new BigDecimal("0.0");
        if (studentAlreadyNum != 0) {
            alreadyRate = new BigDecimal(studentAlreadyNum).multiply(new BigDecimal("100")).divide(new BigDecimal(ValueNum), 1, BigDecimal.ROUND_HALF_UP);
        }
        reserveCollegeVo.setAlreadyRate(alreadyRate);
        // 预约今天报道的人数
        long studentReserveTodayNum = reserveList.stream().filter(reserve -> DateUtil.today().equals(DateUtil.formatDate(com.orientation.utils.DateUtil.localDateTimeToDate(reserve.getReserveTime())))).count();
        reserveCollegeVo.setStudentReserveTodayNum((int) studentReserveTodayNum);
        // 今天实际报到的人数 todo 修改的时间类型
       reserveList= reserveList.stream().filter(reserve -> ObjectUtils.isNotEmpty(reserve.getRealTime())).collect(toList());
        long studentTodayNum = reserveList.stream().filter(reserve -> DateUtil.today().equals(DateUtil.formatDate(com.orientation.utils.DateUtil.localDateTimeToDate(reserve.getRealTime()))) && reserve.getStatus().equals(3)).count();
        reserveCollegeVo.setStudentTodayNum((int) studentTodayNum);
        BigDecimal todayRate = new BigDecimal("0.0");
        if (studentTodayNum != 0) {
            if (studentTodayNum < studentReserveTodayNum) {
                todayRate = new BigDecimal(studentTodayNum).multiply(new BigDecimal("100")).divide(new BigDecimal(studentReserveTodayNum), 2, BigDecimal.ROUND_HALF_UP);
            } else {
                todayRate = new BigDecimal(0.0);
            }
        }
        reserveCollegeVo.setTodayRate(todayRate);
        return reserveCollegeVo;
    }


    /**
     * 按中文首字母排序
     *
     * @param result
     * @return result
     */
    private List<College> comparatorForChina(List<College> result) {
        Comparator comparator = Collator.getInstance(Locale.CHINA);
        Collections.sort(result, (o1, o2) -> comparator.compare(o1.getCollegeName(), o2.getCollegeName()));
        return result;
    }
}
